package smlab.image
{
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Shape;
	import flash.display.Sprite;
	//import flash.utils.getTimer;
	
	/**
	 * 将显示对象进行马赛克处理
	 * @author simon
	 * 
	 */
	public class Mosaic_SM extends Sprite{
		
		private var bmd:BitmapData;
		public var pixelSize:uint;//设置马赛克程度
		private var cache:Object = {};
		public var useCache:Boolean;
		
		//testing vars
		//var totalTime:uint = 0;
		
		/********************
		 
		 Mosaic class - Julian Kussman
		 
		 constructor:
		 var myMosaic:Mosaic = new Mosaic(DisplayObject, [pixelSize = 0], [useCache = true]);
		 
		 public vars:
		 pixelSize:uint //sets size of mosaic pixels
		 useCache:Boolean //to use a cache or not
		 
		 public methods:
		 render():void //renders the mosaic, called automatically after instantiation if pixelSize is > 0.
		 
		 The render algorithm draws one extra row and column of pixels to keep the final product the same size as the copied original image.
		 
		 The cache will store all rendered Sprites for each size and if you try to render a cached size it will not redraw it and instead display it from the cache.
		 
		 ********************/
		
		public function Mosaic_SM(srcDispObj:DisplayObject, _pixelSize:uint = 0, _useCache:Boolean = true){
			
			bmd = new BitmapData(srcDispObj.width, srcDispObj.height);
			bmd.draw(srcDispObj);
			
			this.pixelSize = _pixelSize
			this.useCache = _useCache;
			
			var masker:Shape = makeRect(bmd.width, bmd.height, 0xCCCCCC);
			addChild(masker);
			this.mask = masker;
			
			if (pixelSize != 0){
				render();
			}else{
				cache[pixelSize] = new Bitmap(bmd);
				addChild(cache[pixelSize]);
			}
			
		}
		
		/**
		 * 更新马赛克效果
		 * 
		 */
		public function render():void{
			
			//var startTime:uint = getTimer();
			
			if (useCache && cache[pixelSize]){
				//trace("cached exists");
				for (var cachedSprite:String in cache){
					if (this.contains(cache[cachedSprite])){
						removeChild(cache[cachedSprite]);
					}
				}
				addChild(cache[pixelSize]);
				
			} else {
				//trace("no cache");
				
				var renderContainer:Sprite = new Sprite();
				
				var ySteps:uint = Math.round(bmd.height / pixelSize);
				var xSteps:uint = Math.round(bmd.width / pixelSize);
				
				for (var i:uint = 0; i <= ySteps; i++){
					var colorY:uint;
					if (i == ySteps){
						colorY = pixelSize * (i - 1);
					}else{
						colorY = pixelSize * (i);
					}
					
					for (var j:uint = 0; j <= xSteps; j++){
						
						var colorX:uint;
						
						if (j == xSteps){
							colorX = pixelSize * (j - 1);
						}else{
							colorX = pixelSize * (j);
						}
						
						var color:uint = bmd.getPixel(colorX , colorY);
						var pixel:Shape = makePixel(pixelSize, color);
						pixel.x = (j * pixelSize);
						pixel.y = (i * pixelSize);
						renderContainer.addChild(pixel);
						
					}
				}
				
				cache[pixelSize] = renderContainer;
				
				for (var cachedSprite2:String in cache){
					if (this.contains(cache[cachedSprite2])){
						removeChild(cache[cachedSprite2]);
					}
				}
				addChild(renderContainer);
				
			}
			
			
			//var rendTime:uint = getTimer() - startTime;
			//totalTime += rendTime;
			//trace("pixel size:", pixelSize, "render time:", rendTime, "total time:", totalTime);
		}
		
		private function makePixel(size:uint, color:uint):Shape{
			
			var pixel:Shape = makeRect(size, size, color);
			
			return pixel;
			
		}
		
		private function makeRect(w:uint, h:uint, color:uint):Shape{
			
			var rect:Shape = new Shape();
			rect.graphics.beginFill(color);
			rect.graphics.drawRect(0, 0, w, h);
			rect.graphics.endFill();
			
			return rect;
			
		}
	}
}


/*
使用实例：
此实例貌似有内存漏洞。。。

import Mosaic_SM;

var myMoz:Mosaic_SM = new Mosaic_SM(显示对象);

myMoz.x = 501;
myMoz.pixelSize = 3;

addChild(myMoz);

var myTimer:Timer = new Timer(100, 10);
myTimer.addEventListener(TimerEvent.TIMER, rend);
myTimer.start();

function rend(e:TimerEvent){
if ( myTimer.currentCount == myTimer.repeatCount){
myTimer.reset();
myTimer.start();
}else{
myMoz.pixelSize = myTimer.currentCount * 3;
myMoz.render();
}
}

*/

/*
使用实例2：

var myMoz:Mosaic_SM = new Mosaic_SM(yourDisplayObj:DisplayObject, pixelSize:uint, useCache:Boolean);
addChild(myMoz);

or

var myMoz:Mosaic_SM = new Mosaic_SM(yourDisplayObj);
myMoz.pixelSize = 10;
myMoz.render();
*/